package dBConnection;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.URL;
import java.net.URLConnection;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import logger.GRIALogger;

import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class dBInstitution {
	private int id;
	private String name;
	private String type;
	private String description;
	private double c1;
	private double c2;
	private double c3;
	private String country;
	private String city;
	private String url;

	public dBInstitution(int id, String name, String type, String description,
			double c1, double c2, double c3, String country, String city,
			String url) {
		this.id = id;
		this.name = name;
		this.type = type;
		this.description = description;
		this.c1 = c1;
		this.c2 = c2;
		this.c3 = c3;
		this.country = country;
		this.city = city;
		this.url = url;
	}

	/**
	 * Constructor that retrieves data from Google Maps.
	 * 
	 * @param id
	 * @param name
	 * @param type
	 * @param description
	 * @param city
	 * @param url
	 * @throws IOException
	 */
	public dBInstitution(int id, String name, String type, String description,
			String city, String url) throws IOException {
		this.id = id;
		this.name = name;
		this.type = type;
		this.description = description;
		this.city = city;
		this.url = url;

		String info = dBInstitution.getGeoInfo(city);

		this.country = info.split(";")[1];
		this.c1 = Double.parseDouble(info.split(";")[2]);
		this.c2 = Double.parseDouble(info.split(";")[3]);

		// String ret = country + " " + c1 + " " + c2;
		this.c3 = 0;
		// SEARCH COORDINATES - END

	}

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public String getType() {
		return type;
	}

	public void setType(String type) {
		this.type = type;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public double getC1() {
		return c1;
	}

	public void setC1(double c1) {
		this.c1 = c1;
	}

	public double getC2() {
		return c2;
	}

	public void setC2(double c2) {
		this.c2 = c2;
	}

	public double getC3() {
		return c3;
	}

	public void setC3(double c3) {
		this.c3 = c3;
	}

	public String getCountry() {
		return country;
	}

	public void setCountry(String country) {
		this.country = country;
	}

	public String getCity() {
		return city;
	}

	public void setCity(String city) {
		this.city = city;
	}

	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	public static String getGeoInfo(String city) throws IOException {
		String ret;
		ret = dBInstitution.getGeoInfoFromCache(city);

		if (ret == null) {
			ret = dBInstitution.getGeoInfoFromGoogle(city);
			if (ret == "") {
				GRIALogger.log("google bad response");
				ret = dBInstitution.getGeoInfo(city);
				GRIALogger.log("google bad response solved: " + ret);
				return ret;
			}
			dBInstitution.fillCache(ret);
			// e scrivo dentro la cache
			return ret;
		} else
			return ret;
	}

	public static String getGeoInfoFromGoogle(String city) throws IOException {
		Document doc = null;
		try {
			doc = dBInstitution.getXmlFromGoogle(city);
		} catch (ParserConfigurationException e) {
			GRIALogger.log("PARSER " + e.getMessage());
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (SAXException e) {
			GRIALogger.log("SAX " + e.getMessage());
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if (doc == null) {
			GRIALogger.log("doc == null");
		}

		// SEARCH COUNTRY

		NodeList n = doc.getElementsByTagName("address_component");

		String country = null;
		String s = null;
		String stype = null;

		for (int i = 0; i < n.getLength(); i++) {
			s = n.item(i).getTextContent();
			stype = s.split("\\n")[3];
			if (stype.trim().equalsIgnoreCase("country")) {
				country = s.split("\\n")[1];
				break;
			}
		}
		if (country == null)
			return "";
		country = country.trim();
		// SEARCH COUNTRY - END

		// SEARCH COORDINATES
		NodeList m = doc.getElementsByTagName("location");

		double c2 = Double.parseDouble(m.item(0).getTextContent().trim().split(
				"\\n")[0]);
		double c1 = Double.parseDouble(m.item(0).getTextContent().trim().split(
				"\\n")[1]);

		String ret = city + ";" + country + ";" + c1 + ";" + c2;
		GRIALogger.log("GOOOOOOOOOOOOOOOOOOOOOOOOOOOGLE!!!;");
		return ret;
	}

	public static String getGeoInfoFromCache(String city) throws IOException {
		FileReader reader = new FileReader("cache.txt");
		BufferedReader buf = new BufferedReader(reader);
		String data;
		while ((data = buf.readLine()) != null) {
			if (data.split(";")[0].equals(city)) {
				// GRIALogger.log("cache hit;");
				return data;
			}
		}
		GRIALogger.log("cache miss;");
		return null;
	}

	public static void fillCache(String data) {
		try {
			FileOutputStream toWrite = new FileOutputStream("cache.txt", true);
			PrintStream output = new PrintStream(toWrite);

			output.println(data);

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		GRIALogger.log("cache fill;");
	}

	// TODO private
	public static Document getXmlFromGoogle(String city)
			throws ParserConfigurationException, SAXException, IOException {
		city = city.replace(' ', '+');
		
		GRIALogger.log("city = " + city);

		URL google = new URL(
				"https://maps.googleapis.com/maps/api/geocode/xml?address="
						+ city + "&sensor=false");
		URLConnection gConn = google.openConnection();

		BufferedReader in = new BufferedReader(new InputStreamReader(gConn
				.getInputStream()));
		String inputLine;
		String output = "";

		while ((inputLine = in.readLine()) != null)
			output = output + inputLine + "\n";
		// System.out.println(inputLine);
		in.close();

		// System.out.println(output);

		try {
			FileOutputStream toWrite = new FileOutputStream("tempFile.xml");
			PrintStream printer = new PrintStream(toWrite);

			printer.println(output);

		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		File myXml = new File("tempFile.xml");
		DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
		DocumentBuilder dBuilder = dbFactory.newDocumentBuilder();
		Document doc = null;
		try{
		doc = dBuilder.parse(myXml);}
		catch(Exception e){
			GRIALogger.log("EXCEPTION: " + e.getMessage());
		}
		return doc;
	}

}
